﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using ExcelDna.Integration;
using Excel = Microsoft.Office.Interop.Excel;
using CrystalWind.Example.ExcelDna.CustomerExtentions;
using ExcelDna.Registration;
using System.Threading;
#if tru

namespace CrystalWind.Example.ExcelDna
{
    public class ExampleAsyncTask
    {


        #region 测试赋值方法
        public static string GetValueMoreTime(int seconds)
        {
            Thread.Sleep(TimeSpan.FromSeconds(seconds));
            return nameof(GetValueMoreTime);
        }
        public static Task<string> GetValueMoreTimeAsync(int seconds)
        {
            return Task.Run(delegate
            {
                return GetValueMoreTime(seconds);
            });
        }
        #endregion


        /// <summary>
        /// 错误做法,直接使用ExcelAsyncUtil.QueueAsMacro
        /// </summary>
        [ExcelCommand(MenuName = "ExampleAsyncTask", MenuText = "Test1", ExplicitRegistration = false)]
        public static void AsyncTask1()
        {
            var cell = DnaExtentions.GetExcelReference("Sheet1", "A1");

            //会阻塞excel,证明里面的委托是被推到excel消息队列中执行,执行在excel线程上
            ExcelAsyncUtil.QueueAsMacro(() =>
            {
                cell.SetValue(GetValueMoreTime(3));
            });
        }


        /// <summary>
        /// 正确,回写excel等操作,才调用ExcelAsyncUtil.QueueAsMacro
        /// </summary>
        [ExcelCommand(MenuName = "ExampleAsyncTask", MenuText = "Test2", ExplicitRegistration = false)]
        public static void AsyncTask2()
        {
            var cell = DnaExtentions.GetExcelReference("Sheet1", "A1");

            //耗时操作放在其他线程,回写excel等操作,放到Macro线程
            Task.Run(delegate
            {
                return GetValueMoreTime(3);
            }).ContinueWith(t =>
            {
                ExcelAsyncUtil.QueueAsMacro(delegate
                {
                    cell.SetValue(t.Result);
                });
            });

        }

        /// <summary>
        /// 使用自定义任务调度器,包装ExcelAsyncUtil.QueueAsMacro的调用
        /// </summary>
        [ExcelCommand(MenuName = "ExampleAsyncTask", MenuText = "Test3", ExplicitRegistration = false)]
        public static void AsyncTask3()
        {
            var cell = DnaExtentions.GetExcelReference("Sheet1", "A1");

            //只是减少了ContinueWith后的委托代码.仍然不能使用await
            GetValueMoreTimeAsync(3)
                .ContinueWith(t =>
                {
                    cell.SetValue(t.Result);
                }, new MyTaskScheduler());
        }

        [ExcelCommand(MenuName = "ExampleAsyncTask", MenuText = "Test4", ExplicitRegistration = false)]
        public static async void AsyncTask4()
        {
            var cell = DnaExtentions.GetExcelReference("Sheet1", "A1");

            //没区别,只是换了形式调用
            string value = await GetValueMoreTimeAsync(3);
            ExcelAsyncUtil.QueueAsMacro(delegate
            {
                cell.SetValue(value);
            });
        }

    }


    /**********************************/


    class MyTaskScheduler : TaskScheduler
    {
        protected override IEnumerable<Task> GetScheduledTasks()
        {
            throw new NotImplementedException();
        }

        protected override void QueueTask(Task task)
        {
            ExcelAsyncUtil.QueueAsMacro(delegate
            {
                TryExecuteTask(task);
            }, task);
        }

        protected override bool TryExecuteTaskInline(Task task, bool taskWasPreviouslyQueued)
        {
            return false;
        }
    }

}

#endif